﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using theeg.GeometryWpf;
using theeg.GraphWpf.Models;
using Node = theeg.GraphWpf.Models.Node;

namespace theeg.GraphWpf.Views
{
    [TemplateVisualState(Name = "MouseOver", GroupName = "CommonStates")]
    [TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
    public class SubGraphPresenter : PresenterBase
    {
        public static readonly RoutedEvent SubgraphExpandedEvent = EventManager.RegisterRoutedEvent(
"SubgraphExpanded", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SubGraphPresenter));

        public event RoutedEventHandler SubgraphExpanded
        {
            add { AddHandler(SubgraphExpandedEvent, value); }
            remove { RemoveHandler(SubgraphExpandedEvent, value); }
        }

        public override IHilbertTreeNode HilbertNode
        {
            get { return Data; }
        }

        public SubGraph Data
        {
            get { return (SubGraph)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }

        public static readonly DependencyProperty DataProperty =
            DependencyProperty.Register("Data", typeof(SubGraph), typeof(SubGraphPresenter), new PropertyMetadata(null, NodeDataChanged));

        private Canvas _sketchPanel;

        private static void NodeDataChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            SubGraphPresenter vnode = (SubGraphPresenter)sender;
            if (e.OldValue != null)
            {
                var oldValue = (SubGraph)e.OldValue;
                oldValue.PropertyChanged -= vnode.SubgraphPropertyChanged;
            }
            if (e.NewValue == null)
            {
                vnode.SetValue(Canvas.LeftProperty, 0);
                vnode.SetValue(Canvas.TopProperty, 0);
            }
            else
            {
                SubGraph node = (SubGraph)e.NewValue;
                vnode.SetValue(Canvas.LeftProperty, node.Left);
                vnode.SetValue(Canvas.TopProperty, node.Top);
                node.PropertyChanged += vnode.SubgraphPropertyChanged;
            }
            vnode.CreatePresenters();
        }

        private void SubgraphPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsExpanded")
            {
                Dispatcher.BeginInvoke((Action)(() => RaiseEvent(new RoutedEventArgs
                {
                    RoutedEvent = SubgraphExpandedEvent,
                    Source = HilbertNode
                })));
            }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            _sketchPanel = GetTemplateChild("sketchPanel") as Canvas;

            CreatePresenters();
        }

        private void CreatePresenters()
        {
            if (_sketchPanel == null || Data == null)
            {
                return;
            }
            var children = _sketchPanel.Children;
            children.Clear();

            foreach (INode obj in Data.Nodes)
            {
                if (obj is SubGraph)
                {
                    children.Add(new SubGraphPresenter
                    {
                        Data = (SubGraph)obj
                    });
                }
                else if (obj is Node)
                {
                    children.Add(new NodePresenter
                    {
                        Data = obj
                    });
                }
            }
            foreach (Transition edge in Data.Transitions)
            {
                children.Insert(0, new TransitionPresenter
                {
                    Data = edge
                });
            }
        }

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            if (e.Property == IsMouseOverProperty)
            {
                CoerceMouseOver(Data, IsMouseOver);
            }
        }

        private void CoerceMouseOver(INode data, bool isMouseOver)
        {
            foreach (var edge in data.IncomingEdges)
            {
                edge.IsHighlighted = isMouseOver;
            }
            foreach (var edge in data.OutgoingEdges)
            {
                edge.IsHighlighted = isMouseOver;
            }
        }
    }
}
